package com.googlecode.framework.web.struts2.actions;

import java.lang.reflect.Constructor;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.math.NumberUtils;
import org.apache.struts2.ServletActionContext;
import org.springframework.util.ClassUtils;

import com.googlecode.framework.core.pagination.Order;
import com.googlecode.framework.core.pagination.OrderablePagination;
import com.googlecode.framework.core.pagination.Paginator;
import com.googlecode.framework.core.utils.StringUtils;
import com.googlecode.framework.web.pagination.AbstractWebPagination;
import com.googlecode.framework.web.pagination.DefaultHref;
import com.googlecode.framework.web.pagination.Href;
import com.googlecode.framework.web.pagination.KeyboardableWebPagination;
import com.googlecode.framework.web.pagination.PaginationConstants;
import com.opensymphony.xwork2.ActionSupport;

public class PaginationableAction extends ActionSupport {

    /**
     * serialVersionUID
     */
    private static final long serialVersionUID = 8044492708798664402L;
    
    private Class<? extends AbstractWebPagination> paginationClass = KeyboardableWebPagination.class;

    /*
     * 分页查询数据
     */
    protected List<?> queryWithPagination(PaginationQueryCallback pqCallback) {
        // 根据Http请求还原WebPagination对象
        AbstractWebPagination awp = makeWebPagination();
        prepareWebPagination(awp);
        // 获取分页数据
        List<?> result = pqCallback.query(awp);
        // 绑定WebPagination对象
        bindWebPagination(awp);
        
        return result;
    }
    
    /*
     * 根据Http请求还原WebPagination对象
     */
    protected AbstractWebPagination makeWebPagination() {
        HttpServletRequest request = ServletActionContext.getRequest();
        
        /*
         * 初始化Href
         */
        String requestURI = request.getRequestURI();
        Href href = new DefaultHref(requestURI);
        href.addParameterMap(request.getParameterMap());
        
        /*
         * 初始化Paginator
         */
        // 总数
        int rows = NumberUtils.toInt(request.getParameter(PaginationConstants.PARAM_ROWS), Integer.MAX_VALUE);
        // 当前页
        int page = NumberUtils.toInt(request.getParameter(PaginationConstants.PARAM_PAGE), 0);
        // sidx
        String sidx = request.getParameter(PaginationConstants.PARAM_SINDEX);
        String sord = request.getParameter(PaginationConstants.PARAM_SORDER);
        Order order = null;
        if (!StringUtils.isEmpty(sidx) && "asc".equalsIgnoreCase(sord)) {
            order = Order.asc(sidx);
        } else if (!StringUtils.isEmpty(sidx) && "desc".equalsIgnoreCase(sord)) {
            order = Order.desc(sidx);
        }
        
        Paginator paginator = new Paginator();
        paginator.setItems(rows);
        paginator.setPage(page);
        
        // 还原WebPagination对象
        Constructor<? extends AbstractWebPagination> c = ClassUtils.getConstructorIfAvailable(paginationClass, Href.class, Paginator.class);
        try {
            AbstractWebPagination awp = c.newInstance(href, paginator);
            if (order != null) {
                awp.addOrder(order);                
            }
            return awp;
        } catch (Exception e) {
            throw new RuntimeException("初始化WebPagination出错！", e);
        }
    }
    
    protected void prepareWebPagination(AbstractWebPagination awp) {
    }
    
    /*
     * 绑定WebPagination对象
     */
    protected void bindWebPagination(AbstractWebPagination awp) {
        ServletActionContext.getRequest().setAttribute(PaginationConstants.DEFAULT_PAGINATION_NAME, awp);
    }
    
    protected static interface PaginationQueryCallback {
        List<?> query(OrderablePagination op);
    }
}
